﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

using Torneo.Entidades;
using Torneo.Front.Models;
using System.Web.Security;
using System.Web.Routing;
using log4net;

namespace Torneo.Front.Controllers
{
    public interface IFormsAuthenticationService
    {
        void SignIn(string userName);
        void SignOut();
    }
    public class FormsAuthenticationService : IFormsAuthenticationService
    {
        public void SignIn(string userName)
        {
            if (String.IsNullOrEmpty(userName)) throw new ArgumentException("Value cannot be null or empty.", "userName");

            FormsAuthentication.SetAuthCookie(userName, false);
        }

        public void SignOut()
        {
            FormsAuthentication.SignOut();
        }
    }
    public class TorneoController : Controller
    {
        public TorneoController()
        {
            log = log4net.LogManager.GetLogger("LogFileAppender");
        }

        public log4net.ILog log;

        public IFormsAuthenticationService FormsService { get; set; }

        public ActionResult Index()
        {
            return View();
        }

        public ActionResult Reglas()
        {
            return View();
        }

        protected override void Initialize(RequestContext requestContext)
        {
            if (FormsService == null) { FormsService = new FormsAuthenticationService(); }
            base.Initialize(requestContext);
        }

        public FileContentResult GetPhoto()
        {
            Jugador jugadorEditado = (Jugador)TempData["JugadorEdit"];
            TempData["JugadorEdit"] = jugadorEditado;
            return File(jugadorEditado.Imagen, "image/png");
        }
        #region Usuarios
        public ActionResult Loguear()
        {
            return View("Loguear");
        }

        public ActionResult DesLoguear()
        {
            FormsService.SignOut();
            return RedirectToAction("Index", "Torneo");
        }
        public ActionResult LoguearUsuario(FormCollection form)
        {
            try
            {
                string username = form["Usuario"].ToString();
                string pass = form["Pass"].ToString();
                Servicio.ServiceClient sc = new Servicio.ServiceClient();
                var usuario = sc.AutenticarUsuario(username, pass);
                if (usuario != null)
                {
                    FormsService.SignIn(usuario.Nombre.ToString());
                }
                return View("ConfirmacionUsuario", new MensajeConfirmacion(true, "Usuario logueado"));
            }
            catch (Exception ex)
            {
                log.Error("LoguearUsuario: ", ex);
                return View("MensajeError", new MensajeError(false, ex.Message));
            }
        }

        [Authorize]
        public ActionResult ListarUsuarios()
        {
            try
            {
                Servicio.ServiceClient sc = new Servicio.ServiceClient();
                List<Torneo.Entidades.Usuario> lst = sc.ObtenerUsuarios().ToList<Usuario>();
                return View("ListadoUsuarios", lst);
            }
            catch (Exception ex)
            {
                log.Error("ListarUsuarios: ", ex);
                return View("MensajeError", new MensajeError(false, "Problema al listar los usuarios"));
            }
        }

        public ActionResult Informacion()
        {
            return View();
        }

        [Authorize]
        public ActionResult CreateUsuario()
        {
            return View("CrearUsuario");
        }

        [Authorize]
        public ActionResult CreateConfirmationUsuario(FormCollection form)
        {
            try
            {
                Usuario usuarioCreado = new Usuario();
                usuarioCreado.Nombre = form["Nombre"].ToString();
                usuarioCreado.Apellido = form["Apellido"].ToString();
                usuarioCreado.User = form["User"].ToString();
                usuarioCreado.Password = form["Password"].ToString();
                Servicio.ServiceClient sc = new Servicio.ServiceClient();
                sc.CrearUsuario(usuarioCreado);
                return View("ConfirmacionUsuario", new MensajeConfirmacion(true, "Usuario creado"));
            }
            catch (Exception ex)
            {
                log.Error("CreateConfirmationUsuario: ", ex);
                return View("MensajeError", new MensajeError(false, ex.Message));
            }
        }

        [Authorize]
        public ActionResult EditUsuario(int id)
        {
            try
            {
                Servicio.ServiceClient sc = new Servicio.ServiceClient();
                Torneo.Entidades.Usuario usuario = sc.ObtenerUsuariosPorId(id);
                TempData["UsuarioEdit"] = usuario;
                return View("EditarUsuario", usuario);
            }
            catch (Exception ex)
            {
                log.Error("EditUsuario: ", ex);
                return View("MensajeError", new MensajeError(false, ex.Message));
            }
        }

        [Authorize]
        public ActionResult EditConfirmationUsuario(FormCollection form)
        {
            try
            {
                Usuario usuarioEditado = (Usuario)TempData["UsuarioEdit"];
                usuarioEditado.Nombre = form["Nombre"].ToString();
                usuarioEditado.Apellido = form["Apellido"].ToString();
                usuarioEditado.Password = form["Password"].ToString();
                Servicio.ServiceClient sc = new Servicio.ServiceClient();
                sc.ModificarUsuario(usuarioEditado);
                return View("ConfirmacionUsuario", new MensajeConfirmacion(true, "Usuario modificado"));
            }
            catch (Exception ex)
            {
                log.Error("EditConfirmationUsuario: ", ex);
                return View("MensajeError", new MensajeError(false, ex.Message));
            }
        }

        [Authorize]
        public ActionResult DeleteUsuario(int id)
        {
            try
            {
                Servicio.ServiceClient sc = new Servicio.ServiceClient();
                Torneo.Entidades.Usuario usuario = sc.ObtenerUsuariosPorId(id);
                sc.EliminarUsuario(usuario);
                return View("ConfirmacionUsuario", new MensajeConfirmacion(true, "Usuario eliminado"));
            }
            catch (Exception ex)
            {
                log.Error("DeleteUsuario: ", ex);
                return View("MensajeError", new MensajeError(false, ex.Message));
            }
        }

        #endregion

        #region Jugadores
        [Authorize]
        public ActionResult ListarJugadores()
        {
            try
            {
                Servicio.ServiceClient sc = new Servicio.ServiceClient();
                List<Jugador> lst = sc.ObtenerJugadores().ToList<Jugador>();
                return View("ListadoJugadores", lst);
            }
            catch (Exception ex)
            {
                log.Error("ListarJugadores: ", ex);
                return View("MensajeError", new MensajeError(false, ex.Message));
            }
        }

        [Authorize]
        public ActionResult CreateJugador()
        {
            return View("CrearJugador");
        }

        [Authorize]
        public ActionResult CreateConfirmationJugador(FormCollection form)
        {
            try
            {
                Jugador jugadorCreado = new Jugador();
                jugadorCreado.Nombre = form["Nombre"].ToString();
                jugadorCreado.Apellido = form["Apellido"].ToString();
                jugadorCreado.Edad = int.Parse(form["Edad"].ToString());
                byte[] buffer = new byte[Request.Files["fileUpload"].ContentLength];
                Request.Files["fileUpload"].InputStream.Read(buffer, 0, buffer.Length);
                jugadorCreado.Imagen = buffer;
                Servicio.ServiceClient sc = new Servicio.ServiceClient();
                sc.CrearJugador(jugadorCreado);
                return View("ConfirmacionJugador", new MensajeConfirmacion(true, "Jugador creado"));
            }
            catch (Exception ex)
            {
                log.Error("CreateConfirmationJugador: ", ex);
                return View("MensajeError", new MensajeError(false, ex.Message));
            }
        }

        [Authorize]
        public ActionResult EditJugador(int id)
        {
            try
            {
                Servicio.ServiceClient sc = new Servicio.ServiceClient();
                Torneo.Entidades.Jugador jugador = sc.ObtenerJugadorPorId(id);
                TempData["JugadorEdit"] = jugador;
                return View("EditarJugador", jugador);
            }
            catch (Exception ex)
            {
                log.Error("EditJugador: ", ex);
                return View("MensajeError", new MensajeError(false, ex.Message));
            }
        }

        [Authorize]
        public ActionResult EditConfirmationJugador(FormCollection form)
        {
            try
            {
                Jugador jugadorEditado = (Jugador)TempData["JugadorEdit"];
                jugadorEditado.Nombre = form["Nombre"].ToString();
                jugadorEditado.Apellido = form["Apellido"].ToString();
                jugadorEditado.Edad = int.Parse(form["Edad"].ToString());
                Servicio.ServiceClient sc = new Servicio.ServiceClient();
                sc.ModificarJugador(jugadorEditado);
                return View("ConfirmacionJugador", new MensajeConfirmacion(true, "Jugador modificado"));
            }
            catch (Exception ex)
            {
                log.Error("EditConfirmationJugador: ", ex);
                return View("MensajeError", new MensajeError(false, ex.Message));
            }
        }

        [Authorize]
        public ActionResult DeleteJugador(int id)
        {
            try
            {
                Servicio.ServiceClient sc = new Servicio.ServiceClient();
                Torneo.Entidades.Jugador jugador = sc.ObtenerJugadorPorId(id);
                sc.EliminarJugador(jugador);
                return View("ConfirmacionJugador", new MensajeConfirmacion(true, "Jugador eliminado"));
            }
            catch (Exception ex)
            {
                log.Error("DeleteJugador: ", ex);
                return View("MensajeError", new MensajeError(false, ex.Message));
            }
        }

        public FileContentResult GetPhotoJugadorDetalle(int jugadorId)
        {
            Servicio.ServiceClient sc = new Servicio.ServiceClient();
            Torneo.Entidades.Jugador jugador = sc.ObtenerJugadorPorId(jugadorId);
            return File(jugador.Imagen, "image/png");
        }
        #endregion

        #region Emparejamientos
        [Authorize]
        public ActionResult ListarEmparejamientos()
        {
            try
            {
                Servicio.ServiceClient sc = new Servicio.ServiceClient();
                List<Torneo.Entidades.Emparejamiento> lst = sc.ObtenerEmparejamientos().ToList<Emparejamiento>();
                return PartialView("ListadoEmparejamientos", lst);
            }
            catch (Exception ex)
            {
                log.Error("ListarEmparejamientos: ", ex);
                return View("MensajeError", new MensajeError(false, ex.Message));
            }
        }

        [Authorize]
        public ActionResult CreateEmparejamiento()
        {
            try
            {
                Servicio.ServiceClient sc = new Servicio.ServiceClient();

                List<Torneo.Entidades.Jugador> lst = new List<Jugador>();

                List<Resultado> lstresult = sc.ObtenerTodos().ToList<Resultado>();
                lst = sc.ObtenerJugadoresSinEmparejamiento().ToList<Jugador>();

                if (lst.Count == 0)
                {
                    return View("ConfirmacionEmparejamiento", new MensajeConfirmacion(true, "No hay emparejamientos a ingresar"));
                }
                else
                {
                    var options = new List<SelectListItem>();
                    IOrderedEnumerable<Jugador> lstOrdenada = lst.OrderBy(x => x.JugadorId);
                    Emparejamiento aCrear = new Emparejamiento();
                    aCrear.JugadorA = lstOrdenada.ElementAt(0);
                    aCrear.JugadorB = lstOrdenada.ElementAt(1);
                    aCrear.Fase = 1;
                    TempData["EmparejamientoACrear"] = aCrear;
                    return View("CrearEmparejamiento", aCrear);
                }
            }
            catch (Exception ex)
            {
                log.Error("CreateEmparejamiento: ", ex);
                return View("MensajeError", new MensajeError(false, ex.Message));
            }
        }

        [Authorize]
        public ActionResult CreateConfirmationEmparejamiento(FormCollection form)
        {
            try
            {
                Servicio.ServiceClient sc = new Servicio.ServiceClient();
                Emparejamiento aCrear = (Emparejamiento)TempData["EmparejamientoACrear"];
                aCrear.Fecha = DateTime.Parse(form["datepicker"].ToString());
                sc.CrearEmparejamiento(aCrear);
                return View("ConfirmacionEmparejamiento", new MensajeConfirmacion(true, "Emparejamiento creado"));
            }
            catch (Exception ex)
            {
                log.Error("CreateConfirmationEmparejamiento: ", ex);
                return View("MensajeError", new MensajeError(false, ex.Message));
            }
        }
        #endregion

        #region Resultados
        [Authorize]
        public ActionResult CreateResultado()
        {
            try
            {
                Servicio.ServiceClient sc = new Servicio.ServiceClient();
                List<Emparejamiento> lst = sc.ObtenerEmparejamientosSinResultado().ToList<Emparejamiento>();

                if (lst.Count == 0)
                {
                    return View("ConfirmacionResultado", new MensajeConfirmacion(true, "No hay resultados a ingresar"));
                }
                else
                {
                    var options = new List<SelectListItem>();

                    foreach (var item in lst)
                    {
                        options.Add(new SelectListItem { Value = item.EmparejamientoId.ToString(), Text = item.JugadorA.Nombre + " Vs " + item.JugadorB.Nombre });
                    }
                    ViewData["OptionsResultado"] = options;
                    return View("CrearResultado");
                }
            }
            catch (Exception ex)
            {
                log.Error("CreateResultado: ", ex);
                return View("MensajeError", new MensajeError(false, ex.Message));
            }
        }

        [Authorize]
        public ActionResult CreateConfirmationResultado(FormCollection form)
        {
            try
            {
                Servicio.ServiceClient sc = new Servicio.ServiceClient();

                Resultado resultadoCreado = new Resultado();
                resultadoCreado.Emparejamiento = sc.ObtenerEmparejamientoPorId(int.Parse(form["OptionsResultado"].ToString()));
                resultadoCreado.ResultadoA = int.Parse(form["ResultadoA"].ToString());
                resultadoCreado.ResultadoB = int.Parse(form["ResultadoB"].ToString());
                if (resultadoCreado.ResultadoA > resultadoCreado.ResultadoB)
                    resultadoCreado.Ganador = resultadoCreado.Emparejamiento.JugadorA;
                else
                    resultadoCreado.Ganador = resultadoCreado.Emparejamiento.JugadorB;

                /* id de resultado = id de emparejamiento */
                resultadoCreado.ResultadoId = resultadoCreado.Emparejamiento.EmparejamientoId;
                sc.AgregarResultado(resultadoCreado);

                List<Resultado> lstResult = sc.ObtenerTodos().ToList<Resultado>();
                IOrderedEnumerable<Resultado> lstOrdenada = lstResult.OrderByDescending(x => x.ResultadoId);
                if ((lstResult != null) && (lstResult.Count % 2 == 0))
                {
                    Emparejamiento nuevoEmparejamiento = new Emparejamiento();
                    nuevoEmparejamiento.JugadorA = lstOrdenada.ElementAt(0).Ganador;
                    nuevoEmparejamiento.JugadorB = lstOrdenada.ElementAt(1).Ganador;
                    nuevoEmparejamiento.Fecha = DateTime.Now;
                    nuevoEmparejamiento.Fase = resultadoCreado.Emparejamiento.Fase + 1;
                    sc.CrearEmparejamiento(nuevoEmparejamiento);
                }
                return View("ConfirmacionResultado", new MensajeConfirmacion(true, "Resultado ingresado"));
            }
            catch (Exception ex)
            {
                log.Error("CreateConfirmationResultado: ", ex);
                return View("MensajeError", new MensajeError(false, ex.Message));
            }
        }

        [Authorize]
        public ActionResult ListarResultados()
        {
            try
            {
                Servicio.ServiceClient sc = new Servicio.ServiceClient();
                EntidadesResultado er = new EntidadesResultado();
                
                er.Jugadores = sc.ObtenerJugadores().ToList<Jugador>();
                er.Resultados = sc.ObtenerTodos().ToList<Resultado>();
                er.Emparejamientos = sc.ObtenerEmparejamientos().ToList<Emparejamiento>(); ;
                return View("ListadoResultados", er);
            }
            catch (Exception ex)
            {
                log.Error("ListarResultados: ", ex);
                return View("MensajeError", new MensajeError(false, ex.Message));
            } 
        }
        #endregion
    }
}
